
// Copyright (c) WanSheng Intelligent Corp. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#ifndef IDR_MGT_SHARED_LIBS_CLIENT_API_IAGENT_CLIENT_API_H_
#define IDR_MGT_SHARED_LIBS_CLIENT_API_IAGENT_CLIENT_API_H_

#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "coap_ext.h"
#include "wa_edge_types.h"
#include "agent_core_lib.h"
#include "wa_alarm.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct WA_EDGE_CONTEXT_TAG * WA_EDGE_CONTEXT;

typedef struct WA_DATA_MONITOR_TAG * WA_DATA_MONITOR;


/*
*    @return:  The WA_EDGE_CONTEXT represents connection to a target wagent device
*/
WA_EDGE_CONTEXT wa_wagent_init(RESTFUL_CONTEXT rest_context, const char * wagent_IP);

RESTFUL_CONTEXT wa_wagent_get_restful_context(WA_EDGE_CONTEXT);

restful_response_t * wa_wagent_request(WA_EDGE_CONTEXT, unsigned int code,
        char *url, char * query,
        char *payload, wa_format_type_t format);

bool wa_wagent_simple_request(WA_EDGE_CONTEXT, unsigned int code,
        char *url, char * query,
        char *payload, wa_format_type_t format);

bool wa_wagent_query_info(WA_EDGE_CONTEXT, iagent_info_t * info);


bool wa_wagent_post_dp(WA_EDGE_CONTEXT, const char * di, char * ri, char * payload, wa_format_type_t fmt);

bool wa_wagent_is_rd_registered(WA_EDGE_CONTEXT agent);


typedef void (*WA_RD_Handler) (WA_EDGE_CONTEXT, bool success);


/*
    @brief  register self on the wagent by posting the RD message
    @param  rd_message        the RD message. It is normally generated from rd_data_payload_A()
    @param  response_handler  handling the response recieved for this request.
                              NULL is supported. call wa_wagent_is_rd_registered() to check the result.
*/
void wa_wagent_register_rd(WA_EDGE_CONTEXT, char * rd_message, WA_RD_Handler response_handler);



/*  @function   wa_wagent_update_rd
    @brief  Update self on the wagent so it keeps in online status
    @param  response_handler  handling the response recieved for this request.
                              NULL is supported. call wa_wagent_is_rd_registered() to check the result.
*/
void wa_wagent_update_rd(WA_EDGE_CONTEXT context, char * di);



/*  @function   wa_wagent_set_rd
    @brief  configure the RD information into the WA_EDGE_CONTEXT object.
            wa_agent_check_rd_registeration() will use the information to finish the RD registration/update task.
    @param  rd_status_handler  handling the response recieved for this request.
                              NULL is supported. call wa_wagent_is_rd_registered() to check the result.
*/
void wa_wagent_set_rd(WA_EDGE_CONTEXT context, const char * device_id, 
        const char * rd_message, int ttl_ms, 
        WA_RD_Handler rd_status_handler);


/*
    @brief  Do the rd registration status handling.
            This function do RD registration and update according to the 
            configurations from wa_wagent_set_rd.
    @return The millisecond to the next check time
*/
uint32_t wa_agent_check_rd_registeration(WA_EDGE_CONTEXT context);


/*  @function   wa_agent_query_rd_A
    @brief      query the resource directory of all the registering devices
*/
char *wa_agent_query_rd_A(WA_EDGE_CONTEXT context);




// wait the response from wagent
bool wa_post_alarm(WA_EDGE_CONTEXT context, iagent_alarm_t* alarm);

bool wa_clear_alarm(WA_EDGE_CONTEXT context, alarm_id_t alarm_id,
        object_type_t target_type,
        const char * target_id,
        const char * reason_reason);

// no waiting for the response
bool wa_eject_alarm_set(iagent_alarm_t* alarm);

bool wa_eject_alarm_clear(alarm_id_t alarm_id, object_type_t target_type, const char * target_id, const char * clear_reason);


// wait for resopnse
bool wa_post_event(WA_EDGE_CONTEXT context, wa_event_t* event);

// no wait for response
bool wa_eject_event2(event_id_t event_id,
        severity_t severity,
        const char * title,
        object_type_t target_type,
        const char * target_id,
        const char * content);
bool wa_eject_event(wa_event_t* event);



WA_DATA_MONITOR wa_monitor_global_new(WA_EDGE_CONTEXT iot_edge, const char * my_app_id, const char * tag,WA_Resource_Handler data_handler);

WA_DATA_MONITOR wa_monitor_res_new(WA_EDGE_CONTEXT iot_edge, const char * my_app_id, const char * tag, const char * di, const char * ri, WA_Resource_Handler data_handler);

void wa_monitor_set_interval_ms(WA_DATA_MONITOR monitor, int ms);

void wa_monitor_set_process(WA_DATA_MONITOR monitor, bool process);

void wa_monitor_set_sequence(WA_DATA_MONITOR monitor, int sequence);

bool wa_monitor_run(WA_DATA_MONITOR monitor);

void wa_monitor_delete(WA_DATA_MONITOR monitor);

typedef struct
{
    char * device_id;
    char * resource_id;
    char * property_name;
    char * tag;
    bool   require_response;
} wa_data_notify_t;

typedef enum
{
    WA_Process_Continue = 0,   // continue the next monitor
    WA_Process_Drop,           // drop this data, subsequencial monitors won't recieve this data
    WA_Process_Modified,        // The next monitor will recive the modified data returned from this monitor
    WA_Process_No_Response
} wa_process_decision_t;

void wa_monitor_free_notification(wa_data_notify_t * notify);
wa_data_notify_t * wa_monitor_parse_notification_A(restful_request_t * request);

/*
    @brief  set the data processing deicsion.
    @note   It should NOT be followed by any call to wa_set_response_status, wa_set_response
            as they will change the decision.
*/
void wa_monitor_set_decision(REQ_ENV_HANDLE req_env, wa_process_decision_t decision);

int wa_monitor_get_decision_code(wa_process_decision_t decision);


#ifdef __cplusplus
}
#endif
#endif /* IDR_MGT_SHARED_LIBS_CLIENT_API_IAGENT_CLIENT_API_H_ */
